package cn.zonhar.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.zonhar.common.exception.AuthorizationException;
import cn.zonhar.common.exception.RRException;
import cn.zonhar.entities.bean.UserBean;
import cn.zonhar.service.LoginService;
import cn.zonhar.utils.*;
import com.alibaba.fastjson.JSON;
import okhttp3.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.testng.collections.Maps;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 登陆
 */
@Service("loginService")
public class LoginServiceImpl implements LoginService {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Override
    public String login(HttpServletResponse response, UserBean userBean) {
        //先去登陆页面获取请求token
        String token = getLoginToken();
        if (!StringUtils.isEmpty(token)) {
            String loginInfoCookie = checkUser(token, userBean);
            if(!StringUtils.isEmpty(loginInfoCookie)){
                //登陆成功后会返回一个url。 获取里面的cookie(登陆令牌)，
                return get160Token(execHealthlogin(token, userBean, loginInfoCookie));
            }
        }
        throw new AuthorizationException("登陆失败");
    }

    private String get160Token(String url) {
        HttpResponse response = HttpRequest.get(url)
                .header("User-Agent", UserAgentUtil.randomUserAgent())
                .header("Origin", "https://www.91160.com")
                .header("Referer", "https://www.91160.com")
                .execute();
        Map<String, List<String>> headers = response.headers();
        List<String> loginInfo = headers.get("Set-Cookie");
        for (String token : loginInfo) {
            if(token.contains("FISKCDDCC")){
                //; path=/; domain=.91160.com
                String replace = token.replace("FISKCDDCC=", "");
                return replace.replace("; path=/; domain=.91160.com","");
            }
        }
        throw new RRException("登陆失败");
    }

    private String checkUser(String token, UserBean userBean) {
        Map<String, String> param = new HashMap<>(5);
        try {
            param.put("username", RsaUtils.encrypt(userBean.getUserName(), PUBLIC_KEY));
            param.put("password", RsaUtils.encrypt(userBean.getPassword(), PUBLIC_KEY));
        } catch (Exception e) {
            throw new AuthorizationException("账户/密码错误！");
        }
        param.put("type", "m");
        param.put("token", token);

        Response response = OkHttpUtils.builder()
                .addHeader("User-Agent", UserAgentUtil.randomUserAgent())
                .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                .addHeader("X-Forwarded-For", IpUtils.getRandomIp())
                .addHeader("Origin", "https://www.91160.com")
                .addHeader("Referer", "https://www.91160.com")
                .url("https://user.91160.com/checkUser.html")
                .addParam(param)
                .postForm().syncResponse();
        List<String> headers = response.headers("Set-Cookie");
        return headers.get(0);
    }

    /**
     * 执行健康160登陆动作
     *
     * @param token    请求的token
     * @param userBean 登陆账户密码
     * @return
     */
    private String execHealthlogin(String token, UserBean userBean,String loginCookie) {
        Map<String, Object> param = Maps.newHashMap();
        String[] split = loginCookie.split(";");
        try {
            param.put("clientLoginUrl", "");
            param.put("username", RsaUtils.encrypt(userBean.getUserName(), PUBLIC_KEY));
            param.put("password", RsaUtils.encrypt(userBean.getPassword(), PUBLIC_KEY));
        } catch (Exception e) {
            throw new AuthorizationException("账户/密码错误！");
        }
        param.put("target", "https://www.91160.com/");
        param.put("error_num", "0");
        param.put("tokens", token);
        HttpResponse httpResponse = HttpRequest.post("https://user.91160.com/login.html")
                .form(param)
                .header("Origin", "https://www.91160.com")
                .header("Host", "user.91160.com")
                .header("Accept", "*/*")
                .header("User-Agent", UserAgentUtil.randomUserAgent())
                .header("Referer", "https://www.91160.com")
                .header("Content-Type", "application/x-www-form-urlencoded").execute();
        int status = httpResponse.getStatus();
        if(302 != status){
            throw new AuthorizationException("账号/密码错误");
        }
        return httpResponse.header("Location");
    }

    /**
     * 获取登陆的token
     *
     * @return
     */
    public String getLoginToken() {
        OkHttpUtils httpUtils = OkHttpUtils.builder();
        String tokenHtml = httpUtils.url("https://user.91160.com/login.html")
                .addHeader("User-Agent",UserAgentUtil.randomUserAgent())
                .addHeader("Referer","https://www.91160.com")
                .addHeader("Origin","https://www.91160.com")
                .get().sync();
        if (StringUtils.isEmpty(tokenHtml)) {
            throw new AuthorizationException("获取登陆token失败，请稍后重试！");
        }
        Document document = Jsoup.parse(tokenHtml);
        String tokens = document.getElementById("tokens").val();
        if (StringUtils.isEmpty(tokens)) {
            //认证失败
            throw new AuthorizationException("获取登陆token失败，请稍后重试！");
        }
        return tokens;
    }

}
